#ifndef _FAT32_PART_H
#define _FAT32_PART_H
#include "fat32_fs.h"
#include "scsi_dev.h"
#include <vector>
using namespace std;

typedef vector<msdos_dir_entry> VEC_FILE_INFO;

typedef struct
{
	char name[12];
	uint64_t lba;
}RECORD_LBA,*PRECORD_LBA;
typedef vector<RECORD_LBA> VEC_FILE_LBA;

//分区信息
typedef struct
{
	char sigFlag[4];
	uint32_t fileNum;
	uint32_t resver4Byte[128-2];
}PART_INFO,*PPART_INFO;
#define  _EXTERN_INFO_
typedef struct _FATFORMAT_PARM_
{
	uint64_t partSecs;		  //分区总扇区数
	char    volume_label[12]; //分区标签名称
#ifdef _EXTERN_INFO_
	char    fileName[8];
    char    fileExt[4];
#endif
}FATFORMAT_PARM,*PFATFORMAT_PARM;

class CFat32Part
{
public:

	CFat32Part(void);
public:
	~CFat32Part(void);
protected:
	CDisk_Dev * m_pdev;			//分区所属的磁盘设备
	fat_boot_sector	m_boot_info;//FAT启动扇区信息

	uint64_t m_base_lba;		//FAT32分区的基本LBA
	uint64_t m_base_data_lba;	//FAT32分区的数据区的起始LBA
	uint64_t m_root_lba;		//根目录文件的LBA

	uint64_t m_base_rec_lba;	//第一个录像文件的起始LBA
	uint32_t m_rec_fsize;		//预录文件大小
	uint32_t m_rec_fsec;		//预录文件所占用的扇区
	uint64_t m_rec_index_lba;   //录像区索引文件
	uint32_t m_reserveMB_space;		//保留扇区
	uint32_t m_root_dir_size;	//根目录大小
	uint32_t m_limit_assignMB;    //最大限制分配空间
	static int FORMAT_POS;      //格式化硬盘进度
public:
	int Init(CDisk_Dev *pdev,uint64_t start_lba);
	int Init(CDisk_Dev * pdev,struct fat_boot_sector* pfat_boot,uint64_t base_lba);
	uint64_t GetFreeSecotr();
	int AssignFile(uint32_t f_size,uint32_t f_num,char* fname_head,char * fname_ext);
	int AssignFileProc(uint32_t f_size,uint32_t & assing_num,char* fname_head,char * fname_ext);
	int AssignFileToFat(uint32_t f_size,uint32_t f_num,char* fname_head,char * fname_ext);
	int AssignFileToFatWithDir(uint32_t f_size,uint32_t f_num,char* fname_head,char * fname_ext);
	int ScanFileInfo(VEC_FILE_INFO* pvec_finfo);
	int ScanFileLBA(VEC_FILE_LBA* pvec_flba);
	int VecFileInfoToFileLBA(VEC_FILE_INFO* pvec_finfo,VEC_FILE_LBA* pvec_flba);
	bool FileNameToLBA(const char* f_name,uint64_t* plba);	//将文件名转换LBA，仅适用预分配文件
	static int FormatParttion(CDisk_Dev * pDev, uint64_t base_lba, FATFORMAT_PARM& formatParm,bool bClearFAT = true);
	static int AddSTFSMagic(fat_boot_sector * pMbs,char * magic,int len);
	static bool IsSTFSPart(char * boot_data);

	static void Mark_FAT_Cluster (unsigned long cluster, unsigned long value, int sectorSize,uchar_t* pFAT);
	static void Mark_FAT_End(unsigned long cluster,int sectorSize,unsigned char* pFat);
	uint64_t  get_eff_space(uint32_t rec_secs);
	uint32_t  count_recIdx_secs(int perInfoSize,int totalIdxNums);
	uint32_t  get_recIndex_size(int perInfoSize,int totalIdxNums);
	int		  create_file(const char * file_name,uint32_t startClu,uint32_t fileSize,uchar_t * data_buf);
	int       create_dir(const char * file_name,uint32_t startClu,uint32_t fileSize,uchar_t * data_buf);
	int		  Mark_FAT_FILE(uint32_t startClu, uint32_t fileSize,uchar_t * pFAT,uint32_t baseClu);
	int       CreateNewFile(const char * file_name,uint32_t fileSize);
	void set_limit_Assign(uint32_t litmit_MB);
#ifdef _WIN32  //Win32 上面的特殊用途
protected:
	char  m_drive_path[8];	//
	HANDLE m_drive_fd;		//句柄
	char  m_part_name[20];	//设备名+分区号
public:
	int lock_volume();
	int	ulock_volume();
	int dis_umount_volume();

public:

	void SetDrivePath(char * drive_path)
	{
		m_drive_path[4] = drive_path[0];
	}

	void SetPhysicalPart(char * drive)
	{
		strcpy(m_part_name,drive);
	}

	char* GetPhysicalPart()	//获取Windows上面的分区的设备名  \\.\X:
	{
		 return m_part_name;
	}

	char* GetDriverPath()
	{
		static char drive_path[4] = "Z:\\";
		drive_path[0] = m_drive_path[4];
		return (char*)drive_path;
	}
#endif
	void SetReserveSpace(uint32_t reseveMB)
	{
		m_reserveMB_space = reseveMB;
	}
public:
	uint64_t GetBaseLba()
	{
		return m_base_lba;
	}
	uint64_t GetTotalSector()
	{
		return m_boot_info.total_sect;
	}

	int GetMaxFileNum(uint32_t file_size)
	{
		return m_boot_info.total_sect /(file_size/m_pdev->get_sec_size());
	}

	uint64_t GetFileLBA(msdos_dir_entry* pfile_info)
	{
		uint32_t cluster_no = (uint32_t)pfile_info->starthi << 16 |  (uint32_t)pfile_info->start;
		return  m_base_data_lba + (cluster_no - 2) * m_boot_info.sec_per_clus;
	}

	uint64_t GetBaseFileLBA()
	{
		return  m_base_data_lba +  3 * m_boot_info.sec_per_clus;
	}

	uint32_t GetRecFileSize()
	{
		return m_rec_fsize;
	}

	uint64_t GetBaseRecFileLBA()
	{
		return m_base_rec_lba;
	}

	uint64_t GetRecIndexLBA()
	{
		return m_rec_index_lba;
	}

	uint64_t GetBaseRecFileSecs()
	{
		return m_rec_fsec;
	}
};

#define  FAT_BOOT_SIZE  512
#define  DIR_INFO_SIZE 32

#define BOOT_LENGTH             512
#define DEFAULT_SECTOR_SIZE     512
#define BOOTCODE_FAT32_SIZE_T   420
#define BOOTCODE_SIZE_T		    448
#define BOOT_SIGN_T             0xAA55
#define MAX_CLUST_32_T          ((1 << 28) - 16)
#define DEFAULT_FAT_NUM         2
#define DBR_RESERVED_SECTORS    34
#define EXTENDED                0x05 //扩展分区标准
#define FAT32                   0x0b //FAT32分区格式
#define MSDOS_FAT32_SIGN        "FAT32   "
#define ATTR_VOLUME_T           8
#define DPT_PARTTION            4  //分区表的最大项数
#define SAVE_PARAT_PARAM_POS    63 //保存分区参数的起始扇区
#define DEF_ROOTDIR_SIZE		SIZE_2MB  //目录表默认使用1M

#define HDIO_GETGEO		        0x0301	/* get device geometry */
#define BLKSSZGET  _IO(0x12,104) /* get block device physical sector size */
#define BLKGETSIZE64  _IOR(0x12,114,size_t)

#endif //_FAT32_PART_H
